﻿using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Shapes;
using System.Reflection;

namespace WenslyWuLib.Common
{
    public class CommandBinder
    {
        #region MouseLeftCommand
        public static ICommand GetMouseLeftDownCommandBinder(DependencyObject obj)
        {
            return (ICommand)obj.GetValue(MouseLeftDownCommandBinderProperty);
        }

        public static void SetMouseLeftDownCommandBinder(DependencyObject obj, ICommand value)
        {
            obj.SetValue(MouseLeftDownCommandBinderProperty, value);
        }

        // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MouseLeftDownCommandBinderProperty =
            DependencyProperty.RegisterAttached("MouseLeftDownCommandBinder",
            typeof(ICommand), typeof(CommandBinder), new PropertyMetadata(ValueChangedCallback));

        private static void ValueChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            UIElement element = d as UIElement;
            if (element != null)
            {
                element.MouseLeftButtonDown += (sender, arg) => { (e.NewValue as ICommand).Execute(element); };
            }
        }
        #endregion


        public static ICommand GetCommand(DependencyObject obj)
        {
            return (ICommand)obj.GetValue(CommandProperty);
        }

        public static void SetCommand(DependencyObject obj, ICommand value)
        {
            obj.SetValue(CommandProperty, value);
        }

        // Using a DependencyProperty as the backing store for CommonCommandBinder.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CommandProperty =
            DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(CommandBinder), new PropertyMetadata(ChangedCallback));

        private static void ChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement element = d as FrameworkElement;
            if (element != null)
            {
                string eventName = element.GetValue(EventNameProperty) as string;
                if (eventName != null)
                {
                    EventInfo eventInfo = element.GetType().GetEvent(eventName);
                    var handler = new RoutedEventHandler((sender, arg) =>
                    {
                        object obj = element.GetValue(ParameterProperty);
                        (e.NewValue as ICommand).Execute(obj);
                    });
                    var del = handler.GetInvocationList()[0];
                    eventInfo.AddEventHandler(element, del);
                }
            }
        }

        public static object GetParameter(DependencyObject obj)
        {
            return (object)obj.GetValue(ParameterProperty);
        }

        public static void SetParameter(DependencyObject obj, object value)
        {
            obj.SetValue(ParameterProperty, value);
        }

        // Using a DependencyProperty as the backing store for Parameter.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ParameterProperty =
            DependencyProperty.RegisterAttached("Parameter", typeof(object), typeof(CommandBinder), new PropertyMetadata(null));

        public static string GetEventName(DependencyObject obj)
        {
            return (string)obj.GetValue(EventNameProperty);
        }

        public static void SetEventName(DependencyObject obj, string value)
        {
            obj.SetValue(EventNameProperty, value);
        }

        // Using a DependencyProperty as the backing store for EventName.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty EventNameProperty =
            DependencyProperty.RegisterAttached("EventName", typeof(string), typeof(CommandBinder), new PropertyMetadata(null));


    }
}
